0%

2019红帽杯easyRE-ACTF新生赛2020rome-[FlareOn4]login-Youngterdrive

@TOC

[2019红帽杯]easyRE

在这里插入图片描述
elf文件,ida64打开,感兴趣的同学也可以开Linux系统看一看文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
 v56 = __readfsqword(0x28u);
v14 = 73;
v15 = 111;
v16 = 100;
v17 = 108;
v18 = 62;
v19 = 81;
v20 = 110;
v21 = 98;
v22 = 40;
v23 = 111;
v24 = 99;
v25 = 121;
v26 = 127;
v27 = 121;
v28 = 46;
v29 = 105;
v30 = 127;
v31 = 100;
v32 = 96;
v33 = 51;
v34 = 119;
v35 = 125;
v36 = 119;
v37 = 101;
v38 = 107;
v39 = 57;
v40 = 123;
v41 = 105;
v42 = 121;
v43 = 61;
v44 = 126;
v45 = 121;
v46 = 76;
v47 = 64;
v48 = 69;
v49 = 67;
memset(v50, 0, sizeof(v50));
v51 = 0;
v52 = 0;
v0 = v50;
sub_4406E0(0LL, v50, 37LL);
v52 = 0;
v1 = v50;
if ( sub_424BA0(v50) == 36 )
{
for ( i = 0; ; ++i )
{
v1 = v50;
if ( i >= (unsigned __int64)sub_424BA0(v50) )
break;
if ( (unsigned __int8)(v50[i] ^ i) != *(&v14 + i) )
{
result = 4294967294LL;
goto LABEL_13;
}
}
sub_410CC0((__int64)"continue!"); // 第一部分处理
memset(&v53, 0, 0x40uLL);
v55 = 0;
v0 = &v53;
sub_4406E0(0LL, &v53, 64LL);
v54 = 0;
v1 = &v53;
if ( sub_424BA0(&v53) == 39 )
{
v3 = sub_400E44((__int64)&v53); // 十次base64处理
v4 = sub_400E44(v3);
v5 = sub_400E44(v4);
v6 = sub_400E44(v5);
v7 = sub_400E44(v6);
v8 = sub_400E44(v7);
v9 = sub_400E44(v8);
v10 = sub_400E44(v9);
v11 = sub_400E44(v10);
v12 = sub_400E44(v11);
v0 = off_6CC090;
v1 = (char *)v12;
if ( !(unsigned int)sub_400360(v12, off_6CC090) )
{
sub_410CC0((__int64)"You found me!!!");
v1 = "bye bye~";
sub_410CC0((__int64)"bye bye~");
}
result = 0LL;
}
else
{
result = 4294967293LL;
}
}
else
{
result = 0xFFFFFFFFLL;
}
LABEL_13:
if ( __readfsqword(0x28u) != v56 )
sub_444020(v1, v0);
return result;
}

第一部分的处理是个异或,第二部分打开函数之后发现是base64的运算(10次),而且得到的结果与off_6cc090比较
先解出第一部分

1
2
3
4
5
str = [73,111,100,108,62,81,110,98,40,111,99,121,127,121,46,105,127,100,96,51,119,125,119,101,107,57,123,105,121,61,126,121,76,64,69,67]
input1 = ''
for i in range(len(str)):
input1 += chr(str[i]^i)
print(input1)

在这里插入图片描述
第二部分用在线工具解十次base64,解出来发现是个网站
https://bbs.pediy.com/thread-254172.htm
打开发现没有用,是个干扰项
看了其他师傅的wp后才知道,在我们base64加密结束后,下面有调用一个sub_400D35的函数
在这里插入图片描述
过去看看
在这里插入图片描述
24行判断第一个和第四个是不是f和g,那就猜测这四个字符是flag。

然后循环24次做异或操作。

1
2
3
4
5
6
num2=[0x40,0x35,0x20,0x56,0x5D,0x18,0x22,0x45,0x17,0x2F,0x24,0x6E,0x62,0x3C,0x27,0x54,0x48,0x6C,0x24,0x6E,0x72,0x3C,0x32,0x45,0x5B]
text2='flag'
key=''
for i in range(0,4):
key=key+chr(ord(text2[i])^num2[i])
print(key)

得到v5 == &YA1
在求出v2

1
2
3
4
5
6
num2=[0x40,0x35,0x20,0x56,0x5D,0x18,0x22,0x45,0x17,0x2F,0x24,0x6E,0x62,0x3C,0x27,0x54,0x48,0x6C,0x24,0x6E,0x72,0x3C,0x32,0x45,0x5B]
key='&YA1'
flag=''
for i in range(0,25):
flag=flag+chr(num2[i]^ord(key[i%4]))
print(flag)

flag是:flag{Act1ve_Defen5e_Test}

[ACTF新生赛2020]rome

在这里插入图片描述
ida 32 ,通过main函数或者字符串搜索都可以找到函数func()
发现其实就是将输入的字符串大写和小写分开进行变换,然后比较输出
在这里插入图片描述
写一个脚本跑一下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
v15= [81,115,119,51,115,106,95,108,122,52,95,85,106,119,64,108]
flag=""

for i in range(16):
for j in range(128):
x=j
if chr(x).isupper():
x=(x-51)%26+65
if chr(x).islower():
x=(x-79)%26+97
if chr(x)==chr(v15[i]):
flag+=chr(j)

print ('flag{'+flag+'}')

flag{Cae3ar_th4_Gre@t}

[FlareOn4]login

网页打开,F12查看HTML源码
在这里插入图片描述
var rotFlag = flag.replace(/[a-zA-Z]/g, function(c){return String.fromCharCode((c <= "Z" ? 90 : 122) >= (c = c.charCodeAt(0) + 13) ? c : c - 26);});这句代码的意思就是将字符后移13位,越界了就转回字母开头,最后得到了字符串PyvragFvqrYbtvafNerRnfl@syner-ba.pbz
其实就是ROT13,找一个在线网站解一下,得到:

1
ClientSideLoginsAreEasy@flare-on.com

flag是:flag{ClientSideLoginsAreEasy@flare-on.com}

Youngter-drive

在这里插入图片描述

kali脱壳
在这里插入图片描述
在这里插入图片描述
ida打开,找到主函数
在这里插入图片描述
大致是这样,我们依次看一下
函数sub_4110FF()
在这里插入图片描述
输出部分:函数sub_411190()
在这里插入图片描述
然后着重看一下两个线程的处理
线程1:StartAddress
在这里插入图片描述
看函数sub_41112C,函数sub_411940
这里会出现报错,函数sub_411940无法反编译
在这里插入图片描述
是由于堆栈不平衡的问题,一般是程序有一些干扰代码,让IDA的反汇编分析出现错误。比如用push + n条指令 + retn来跳转。搜索这个函数,看汇编窗口:
在这里插入图片描述
Option->General->Disassembly, 将选项Stack pointer打钩
在这里插入图片描述
然后就可以看见汇编窗口汇编指令前面有绿色的SP值
在这里插入图片描述
找到这串函数的retn指令
在这里插入图片描述
可以发现前面的SP值变成了负数,我们需要修改它成0使得堆栈保持平衡。
找到距离retn最近的call指令
在这里插入图片描述
alt+k修改SP值
在这里插入图片描述
修改之后
在这里插入图片描述
然后就可以可以查看
在这里插入图片描述
线程2:函数sub_41119F()
在这里插入图片描述
线程2并不对代码做任何处理,只是调用一次Sleep然后释放线程。

这里说一个细节,这道题是线程1和线程2 交替执行的,因为函数CreateMutex()
在这里插入图片描述
这个函数是创建两个相互排斥的线程的函数,hobject 可以理解为一个“锁”,两个线程依次获取锁(waitforsingleobject),释放锁(releasemutex)。一个线程开始之后,抢占了锁,这时候另一个线程没抢到,处于等待状态,等待运行线程执行完成之后第一个线程解锁。
不能用来控制两个以上的线程,因为剩下的几个线程都有几率抢到,会导致程序逻辑混乱。
两个线程时候,第一次抢到锁的线程在释放后也会和第二个线程抢锁,但是由于它此时没有第二个线程快,所以抢不到,就造成了两个线程交替被调用的现状。

所以这题就是奇数的会被线程1处理而偶数走线程2 不处理(因为是从29往下减的)

写脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <stdio.h>
int main()
{
char off1[] = "TOiZiZtOrYaToUwPnToBsOaOapsyS";
char off2[] = "QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm";
char flag[30]={0};
int i,j;
for(i=28;i>-1;i--)
{
if(i%2==0)
{
flag[i] = off1[i];
continue;
}
for(j=0;j<52;j++)
{
if(off1[i] == off2[j])
{
flag[i] = j+38;
if(!(flag[i]>=65 &&flag[i]<=90))
flag[i] = j+96;
break;
}
}
}
puts(flag);
return 0;
}

在这里插入图片描述
这里还有一个问题,就是最后输出flag的函数,它显示的是比较i<29
而实际上进程处理的时候是到>-1的,也就是其实应该是30个字符
也就是说少了一位我们不知道,需要一个个英文字母试出来,发现是“E”

flag:flag{ThisisthreadofwindowshahaIsESE}